home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Communication
/
LibraryOfCongress
/
Source
/
state.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-06
|
8KB
|
339 lines
/*
* State machine abstraction.
* The idea is to keep as much of the hookup dialog
* as possible in a text file, so that hookup protocols
* are easy to change here or in other apps.
* It has grown a few warts.
*
* M. J. Hawley
* mike@media-lab.mit.edu
* Copyright (c) November 1991, MIT Media Laboratory.
*/
extern strlen(), Command(), message(), Put(), Flush(), logout();
extern strcpy(), pgets(), strcmp();
extern char *index(), *rindex();
void setState();
typedef enum { Plain, Pattern, Status, Goto, FlushS, Pause, CmdS } SType;
typedef struct String {
char *s;
struct String *next;
} String;
typedef struct {
int type;
char *name;
char *first, *last, *label;
String *l;
} State;
#include "util.h"
SType lastType = Plain;
char *getStr(s,t) char *s, *t; {
char end = ' ';
*t = '\0';
s = skipsp(s);
lastType = Plain;
switch (*s){
Case '/': lastType = Pattern;
Case '+': lastType = Status; s++;
Case '!': lastType = CmdS; s++;
Case ',': lastType = FlushS; s++;
Case '=': lastType = Goto; s = skipsp(s+2);
}
if (*s=='/' || *s == '"') end = *s++;
while (*s && !(*s == end || (end==' ' && *s == '\t'))){
*t = *s++;
if (*t == '\\') switch (*s){
Case 'n': *t = '\n'; s++;
Case 't': *t = '\t'; s++;
Case 'b': *t = '\b'; s++;
Default : *t = *s; s++;
}
t++;
}
*t = '\0';
if (*s && *s != ' ' && *s != '\t') ++s;
if (*s) s = skipsp(s);
return s;
}
State *
newState(s) char *s; {
State *S = Alloc(State);
S->name = save(s);
return S;
}
String *
addStr(s,t) String *s; char *t; {
String *start = s, *n = Alloc(String);
char *p;
p = n->s = save(t);
if (*p=='/' && (p = index(p+1,'/'))){
while (p[-1]=='\\') p = index(p+1,'/');
if (p) *p = '\0';
}
if (!s) return n;
while (s->next) s = s->next;
s->next = n;
return start;
}
void
addString(S,s) State *S; char *s; {
stripnl(s=skipsp(s));
S->l = addStr(S->l,s);
}
#define MaxS 256
static State *ST[MaxS];
static int NS = 0;
void
readState(f) FILE *f; {
char s[1024], n[1024];
State *S = (State *)0;
while (fgets(s,sizeof s,f)){
stripcomment(s);
if (blank(s)) continue;
if (match(s,"[a-zA-Z]*:")){
sscanf(s,"%[^:]",n);
S = newState(n);
ST[NS++] = S;
} else
if (S){
addString(S,s);
}
}
}
State*
state(s) char *s; {
int i;
s = skipsp(s);
for (i=0;i<NS;i++)
if (strcmp(s,ST[i]->name)==0) return ST[i];
return (State *)0;
}
char *str(s) char *s; { return s? s : ""; }
void
printState(s) State *s; {
if (!s) printf("huh?\n"); else
printf("%s: %s %s %s\n",s->name,str(s->first),str(s->last),str(s->label));
}
void
ReadState(s) char *s; {
FILE *f;
if (!NS){
f = fopen(s,"r");
if (f) readState(f), fclose(f);
}
setState("Attach");
}
State *curState = (State *)0;
void
setState(s) char *s; {
curState = state(s);
if (strcmp(s,"Detach")==0) logout();
if (strcmp(s,"Ready")==0) ready();
}
void
execute(s) char *s; {
char t[1024];
if (s[0]=='/') s += strlen(s)+1;
while ((s=getStr(s,t)) && *t) switch (lastType){
Case CmdS: Command(t);
Case Status : message(t);
Case Plain : if (!state(t)) Put("%s",t);
Case FlushS : Flush(t);
Case Goto : setState(t);
}
}
void
execState(s,t) State *s; char *t; {
String *l;
if (!s) s = curState;
if (!s || !s->l) return;
for (l=s->l; l; l=l->next){
if (l->s[0]!='/') execute(l->s);
else
if (l->s[0]=='/' && *t && match(t,l->s+1)) execute(l->s);
}
}
void
runState(s) char *s; {
execState(curState,s);
}
#define FAILED -1
#define LIST 1
#define LISTA 2
#define ITEM 3
int LastItem = 0;
int MoreItems=0;
#define MaxItems 10000
typedef struct {
int n;
char s[128];
} Item;
Item I[MaxItems];
int NI=0;
resetItems(){ NI=0; }
char *
skipdigit(s) char *s; { while (isdigit(*s) && *s) ++s; return skipsp(s); }
copynl(t,s) char *t, *s; {
while ((*t = *s) && *t != '\n')
t++, s++;
*t = '\0';
if (*s == '\n') ++s;
return s;
}
addItemList(s) char *s; {
char t[256];
int date, numtitles;
char author[80], title[80];
char *pt = " ";
s = skipsp(s);
if(LastItem==LIST){ // # titles Authors...
while(*s){
I[NI].n = atoi(s); s = skipdigit(s);
numtitles = atoi(s); s = skipdigit(s);
s = copynl(t,s);
sprintf(I[NI].s,"%4d %s",numtitles,t);
NI++;
}
} else { // # Auth[22] title date
while (*s){
I[NI].n = atoi(s); s = skipdigit(s);
*title = *author = '\0';
s = copynl(title,s);
if (strlen(title)<=22)
s = copynl(author,s);
date = atoi(s); s = skipdigit(s);
if (*author) sprintf(I[NI].s," %s -- %s [%d]",title,author,date);
else sprintf(I[NI].s," %s -- %s [%d]",pt,title,date);
NI++;
}
}
message("found %d.",NI);
}
char *
nthItem(n){
return n<NI? I[n].s : "";
}
nthItemIndex(n){
return n<NI? I[n].n : 0;
}
cleanHighlight(t) char *t; {
char *p = t;
if (*p == 27) ++p;
if (*p == '[' && p[1] == '1' && p[2] == 'm')
strcpy(t,p+3);
}
int MustReload = 0;
char *
getReport(buf, reload) char *buf; {
char *p = buf;
char t[1024], c;
int n = 1, More = 3, more=0;
int flush=0;
MustReload = reload;
message("found 0");
LastItem = 0;
*p++ = '\n';
MORE:
flush=more=0;
while ((c=pgetc()) && c != '>'){
t[0] = c; pgetsx(t+1);
cleanHighlight(t);
cleanEsc(t); strcpy(t,skipsp(t));
if (blank(t) || (t[0]=='n' && t[1]=='\n')) continue;
if (Verbose) printf("+%s",t);
if (strindex(t,"Your search:")) continue; else
if (strindex(t,"Your search for")) flush++, LastItem=FAILED; else
if (strindex(t,"When searching for")) flush++, LastItem=FAILED; else
if (strindex(t,"Type of Material:")) LastItem = ITEM; else
if (strindex(t,"# titles ------")) LastItem = LIST; else
if (strindex(t,"# --------Author-------- ")) LastItem = LISTA; else
if (strncmp(t,"LINE",4)==0){
if (Verbose) printf("++LINE\n");
LastItem = LIST;
continue;
}
if (t[1]=='=') continue;
if (strncmp(t,"No more records",14)==0) More=more=0, flush++;
if (strncmp(t,"# ",4)==0) continue;
if (strncmp(t,"----",7)==0) flush++;
if (strncmp(t,"Enter:",6)==0) flush++;
if (strncmp(t,"(More)",6)==0) more++, More--, flush++;
if (strindex(t,"HINTS:")) flush++;
if (strncmp(t,"Line #",6)==0) flush++;
if (flush) continue;
if (LastItem == ITEM && strncmp(t,"(Record ",8)==0) continue;
if (LastItem == ITEM && (!index(t,':') || index(t,':')[-1] ==' ')){
--p;
if (*p != ' ') *p++ = ' ';
}
strcpy(p,t); p += strlen(p);
}
pgetc(); // read the other '>'
if (more && (More > 0 || LastItem == ITEM)){
Put("n\r");
goto MORE;
}
if (LastItem == ITEM){
Put("b\r"); pgets(t);
}
MoreItems = more;
if (LastItem != ITEM) enableMore(MoreItems);
message("found %d",LastItem==ITEM? 1 : n-1);
*p = '\0';
if (LastItem != ITEM) addItemList(buf);
return buf;
}
getItem(buf,n) char *buf; {
char t[256];
extern reload();
Put("%d\r",n); pgets(t);
resetItems();
getReport(buf,0);
if (LastItem == ITEM) return 1;
MustReload = 1;
DPSAddTimedEntry(1.0,reload,0,10);
return 0;
}